#include <ESP8266WiFi.h>          //https://github.com/esp8266/Arduino

#include <DNSServer.h>
#include <ESP8266WebServer.h>

#include <ESP_WiFiManager.h>   
#include <ESP8266TimerInterrupt.h>

#include <base64.h>
#include <ArduinoJson.h>
#include <MQTT.h>

#define MQTT_HEART_TIMER_INTERVAL_MS        5000 

const char* mqtt_server = "mq.tongxinmao.com";//MQTT服务器的地址 
const int mqtt_port=18830;//MQTT服务器端口号
String m_ChipId;

WiFiClient net;
MQTTClient mqttclient;
ESP8266Timer mqttheartTimer;

void ICACHE_RAM_ATTR mqtt_heart_TimerHandler(void)
{
  if(mqttclient.connected()) {
      StaticJsonDocument<200> actiondoc;
      actiondoc["device"] = m_ChipId;
      actiondoc["status"] = "on";
      char actiondocDoc[measureJson(actiondoc) + 1];
      serializeJson(actiondoc, actiondocDoc, measureJson(actiondoc) + 1); 
      mqttclient.publish("home/status/",actiondocDoc );
  }
}

void mqtt_reconnect() {//等待，直到连接上服务器
  if(WiFi.status() != WL_CONNECTED)
  {
    mqttclient.disconnect();
    return;
  }
   
  while (!mqttclient.connected()) {//如果没有连接上
    if(WiFi.status() != WL_CONNECTED) {
      mqttclient.disconnect();
      Serial.println("MQTT disconneded.");
      break; 
    }

    Serial.println("MQTT server connecting...");    
    if (mqttclient.connect("biloba"+random(999999999))) {//接入时的用户名，尽量取一个很不常用的用户名
      Serial.println("mqtt server connected.");

      // 开始订阅消息
      mqttclient.subscribe("AKINGLED",2);

      // 消息订阅成功
      Serial.println("message subscribe success.");
    } else {
      Serial.println("connect mqtt server failed,try again connect mqtt server in 5 seconds");//延时5秒后重新连接           
      delay(5000);
    }
  }
}

void mqtt_messageReceived(String &topic, String &payload) {
  Serial.println("incoming: " + topic + " - " + payload);

  StaticJsonDocument<200> doc; //声明一个JsonDocument对象
  DeserializationError error = deserializeJson(doc, payload.c_str()); //反序列化JSON数据

  if(!error) {
    String action = doc["action"];

    if (action.equals("on") == true) {
      StaticJsonDocument<200> actiondoc;
      actiondoc["action"] = "on light";
      char actiondocDoc[measureJson(actiondoc) + 1];
      serializeJson(actiondoc, actiondocDoc, measureJson(actiondoc) + 1);     
      mqttclient.publish(topic+"1",actiondocDoc,false,2);
    }
  }  
}

void setup() {
  Serial.begin(115200);

  m_ChipId = (String)ESP.getChipId();

  ESP_WiFiManager ESP_wifiManager("AutoConnectAP");
  ESP_wifiManager.setDebugOutput(true);
  ESP_wifiManager.setTimeout(180);
  ESP_wifiManager.setAPStaticIPConfig(IPAddress(192, 168, 4, 1), IPAddress(192, 168, 4, 1), IPAddress(255, 255, 255, 0));
  ESP_wifiManager.setMinimumSignalQuality(-1);
  
  String Router_SSID = ESP_wifiManager.WiFi_SSID();
  String Router_Pass = ESP_wifiManager.WiFi_Pass();
  Serial.println("Stored: SSID = " + Router_SSID + ", Pass = " + Router_Pass);
  
  String AP_PARAMES = "ESP_" + m_ChipId;    
  ESP_wifiManager.autoConnect(AP_PARAMES.c_str(),AP_PARAMES.c_str(),Router_SSID.c_str(),Router_Pass.c_str());

  mqttclient.begin(mqtt_server,mqtt_port, net);
  mqttclient.onMessage(mqtt_messageReceived);  

  mqttheartTimer.attachInterruptInterval(MQTT_HEART_TIMER_INTERVAL_MS * 1000, mqtt_heart_TimerHandler);    

  String encoded = base64::encode("dsfdsfds");
  
  Serial.println("connected...yeey :)");
}

void loop() {
  mqtt_reconnect();//确保连上服务器，否则一直等待。
  
  mqttclient.loop();//MUC接收数据的主循环函数。
  delay(10);
}
